package solver.moves;

import java.util.Collections;
import java.util.List;

import model.MachineSelector;
import model.Solution;
import model.SolverEnvironment;

public class MachineLoadEliminator extends AbstractComplexMove{
	
	MachineSelector ms;
	
	public MachineLoadEliminator(SolverEnvironment env, MachineSelector ms) {
		super(env);
		this.ms = ms;
	}
	
	@Override
	public boolean performMove() {
		boolean success = false;
		long init_cost=getCc().getNewSolutionCost();
		Solution pot_sol = env.getPotentialSolution();
		long local_cost = init_cost;
		
//		boolean useLocal = random.nextBoolean();

//		int start = getRandom().nextInt(getProblem().M);
//		for(int _m=start;_m<start+getProblem().M;_m++){
//		int curr_m1_index = _m%getProblem().M;
		
//		for(Integer curr_m1_index:ml){
		
//		int start = Math.min(getRandom().nextInt(10), getProblem().M);
		int start = 0 ;
		
		int end = Math.min(start+10+getRandom().nextInt(20), getProblem().M);
//		ms.updateStructureWithLoad();
		List<Integer> ml = ms.getMachineIds();
		for(int m=start;m<end;m++){
			int curr_m1_index = ml.get(m);
			local_cost=getCc().getNewSolutionCost();
			long lc = pot_sol.load_cost_contribution_zipped[curr_m1_index];
			
			if(lc<=0) continue;		
				
			List<Integer> l1 = pot_sol.getProcessesForMachine(curr_m1_index);
			Collections.shuffle(l1,getRandom());
			for(Integer p2:l1){
//				if (testRandom(p2, problem.M/4)){
				int lstart = getRandom().nextInt(getProblem().M);
				int bm = testSequentiallyBestNoSchedule(p2, curr_m1_index, lstart, lstart+getProblem().M);
				if (bm!=-1 && bm!=curr_m1_index){
					long new_cost = local_cost+getCc().getProcessMoveToMachineCost(pot_sol, p2, curr_m1_index, bm);
//					long delta=getCc().getProcessMoveToMachineCost(pot_sol, p2, curr_m1_index, bm);				
//					if((useLocal && new_cost>local_cost) || new_cost>init_cost){
//					if(delta<=0){
					if(new_cost<=init_cost){
						makeMove( p2, curr_m1_index, bm);
//						local_cost = new_cost;
						getCc().updateNewSolutionCost();
						success=true;
//						lc = getCc().getLoadCost(getCurrent_solution(), curr_m1_index);
//						if(local_cost > new_cost)
							break;
					}
				}
			}
//			if (0.95*init_cost>local_cost)
//				return true;
		}
		
		getCc().clearDelta();		

		return success;
	}
}
